import UIKit

var str = "Hello, playground"

//实例方法
//创建一个数学类
class Math {
    //提供一个加法的实例函数
    func add(param1:Double,param2:Double) -> Double {
        return param1 + param2
    }
}

//创建数学类实例
var obj = Math()
//实例对象通过点语法调用实例方法
let result = obj.add(param1: 1, param2: 2)
print(result)


//在Swift语言中，类的每个实例中都默认隐藏着一个名为self的属性，
//可以简单理解为，self就是实例本身，开发者可以在实例方法中通过self来调用类的属性和其他实例方法

//Swift语言中的类型有值类型与引用类型之分。对于引用类型，在实例方法中对实例属性进行修改是没问题的。
//但是对于值类型，读者需要格外注意，使用mutating关键字修饰实例方法才能对属性进行修改
//创建一个结构体
struct Point {
    var x:Double
    var y:Double
    //将x,y值进行修改,需要使用mutating修改方法
    mutating func move(x:Double,y:Double){
        self.x += x
        self.y += y
    }
}

//创建Point结构体实例
var point1 = Point(x: 2, y: 3)
point1.move(x: 2, y: 2)

print(point1.x,point1.y)

//实际上，在值类型实例方法中修改值类型属性的值就相当于创建了一个新的实例，上面的代码和下面的代码在原理上是一致的：
struct Point2 {
    var x:Double
    var y:Double
    //将x,y值进行修改,需要使用mutating修改方法
    mutating func move(x:Double,y:Double){
        self = Point2(x: self.x+x, y: self.y+y)
    }
}
var point2 = Point2(x: 4, y: 4)
point2.move(x: 1, y: 1)
print(point2.x,point2.y)

//类方法是关联于整个类型的，被整个类型所共享。
//对比类属性，Swift语言中的类方法也是通过static和class关键字来声明的，
//static关键字声明的类方法又被称为静态方法，其不能被子类覆写，
//而class关键字声明的类方法可以被类的子类覆写。
//在类方法中也可以使用self关键字，但此时self关键字不再代表实例本身，
//而是代表当前类。在类方法中使用self可以对当前类型的类属性和类方法进行调用。
//为Point结构体提供一个静态方法

struct Point3 {
    var x:Double
    var y:Double
    //将点进行移动,因为修改了属性的值,所以需要用mutating修饰方法
    mutating func move(x:Double,y:Double){
        self.x += x
        self.y += y
    }
    
    //提供一个静态属性
    static let name = "Point3"
    static func printName(){
        //使用self调用静态属性
        print(self.name)
    }
}

//使用结构体名称直接调用静态方法
Point3.printName()


//对于类来说,使用class关键字声明的类方法可以被子类覆写

class SuperClass {
    class func hello(){
        print("Hello")
    }
}

class SubClass:SuperClass{
    override class func hello() {
        print("sub Hello")
    }
}

SubClass.hello()
